package map;

import org.junit.Test;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/*
* Map:存储双列数据, key - velue
*   HashMap:作为Map的主要实现类,可以存储null的key和value
*
*       LinkedHashMap:保证遍历元素是,按照添加的顺序来遍历
*                     在HashMap的底层结构上,添加了一对指针,执向前一个和后一个元素
*                     对于频繁的遍历操作,此类效率比HashMap高
*
*   TreeMap:可以按照添加的键对进行排序,实现遍历排序
*
*
*   Hashtable:最古老的键值对实现类;线程安全,效率低
*
*       Properties:常用来处理配置文件.key和value都是String类型
*
*   面试题:
*       1:HashMap的底层实现原理
*       2:HashMap和Hashtable的异同
*       3:CurrentHashMap 与 HashMap的异同
*
*       1:HashMap的底层实现原理:以JDK7为例
*           在实例化以后,底层创建了长度为16的一维数组entry[] table.
*
*           map.put(key1,value1);
*           首先,计算key1所在类的hashCode()计算哈希值,此哈希值经过某中算法计算后,得到entry在数组中的粗出位置.
*               如若此位置数据为空,添加成功.----情况1
*               如果此位置数据不为空,比较key1和此位置已经存在的key的哈希值,
*                   如果key1的哈希值和其他的不同,添加成功----情况2
*                   如果key1和此位置的一个key相同,继续比较,调用equals()
*                       如果返回false,添加成功----情况3
*                       如果返回true,使用value1替换相同的key的value值,修改旧的value值.
*
*
*           补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的形式存储
*               在不断添加过程中,当超出临界值,且要存储的位置非空,会进行扩容,默认扩容2倍,将原来的数据拷贝进来
*       JDK8的不同:
*           1:new HashMap();底层没有创建一个长度为16的数组
*           2:底层数组是Node[],不是Entry[]
*           3:首次调用put方法是,底层创建长度为16的数组
*           4:JDK7的底层结构只有:数组+链表,JDK8中底层结构:数+链表+红黑树
*               当数组某一索引位置的链表形式的长度>8并且当前数组长度>64时,
*               此时此位置上的所有数据改为使用红黑树进行存储
*
*   思考:为什么map要提前进行扩容:
*       以为map是根据哈希值散列排布的,不一定能够完整的用完所有的内存空间,可能在某一元素下形成一个很长的链表,所以为了防止形成单个长链表,就要提前扩容,保持数据的散列度,这样数据的存取效率都会更高
* */
public class MapTest {

    @Test
    public void test1(){
        Map map = new HashMap();
        map.put(null,null);
        System.out.println(map);//{null=null}

        //Hashtable中的key和value不能是null
//        Hashtable<Object, Object> table = new Hashtable<>();
//        table.put(null,null);
//        System.out.println(table);
    }
}
